package org.terot.framework.fuzzy.instance;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;

import org.terot.util.Logg;

final class ConstructorInstantiator {
	
	/**
	 * 
	 * @param <T>
	 * @param cl
	 * @return
	 */
	protected static<T> Collection<T> generateInstances(Class<T> cl) {

		ArrayList<T> list = new ArrayList<T>();
		
		for (Constructor<?> con : cl.getDeclaredConstructors()) {
        	
        	try {
				
        		Logg.info("Calling constructor " + con.getName());
        		list.add(createInstance(cl, con));
			} catch (IllegalAccessException e) {
				
				Logg.info("Constructor call failed;  illegal access");
			} catch (InvocationTargetException e) {
				
				Logg.info("Constructor call failed; invocation target");
			} catch (IllegalArgumentException e) {
				
				Logg.info("Constructor call failed;  illegal argument");
			} catch (InstantiationException e) {
				Logg.info("Constructor call failed;  instantiation");
			}
        }
		
		return list;
	}
	
    /**
     * Create unset fuzzy instance for a specific constructor 
     * @param cl
     * @param instance
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException 
     * @throws IllegalArgumentException 
     */
	@SuppressWarnings("unchecked")
    private static<T> T createInstance(Class<T> cl, Constructor<?> instance) throws IllegalAccessException, InvocationTargetException, IllegalArgumentException, InstantiationException {
        
    	ArrayList<Object> params = new ArrayList<Object>();

        for(Class<?> param : instance.getParameterTypes()) {
            params.add(Instantiator.createUnsetFuzzyInstances(param));
        }
        
    	return (T) instance.newInstance(params.toArray());
    }
}
